﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ServiceModel.Dispatcher;
using System.Xml;
using System.Xml.Schema;
using System.IO;
using System.ServiceModel.Channels;
using System.ServiceModel.Description;
using Spike.ServiceFramework.ServiceModel.Audit;
using System.Diagnostics;
using Spike.ServiceFramework.ServiceModel.Registration;

namespace Spike.ServiceFramework.ServiceModel
{
    public class DispatchMessageInspector : IDispatchMessageInspector, IEndpointBehavior
    {
        public DispatchMessageInspector(ServiceBehaviorExtension behavior)
        {
            Behavior = behavior;
        }

        protected ServiceBehaviorExtension Behavior { get; set; }
        protected bool ShouldAudit { get { return Behavior.Audit != null; } }
        protected bool RestrictAccess { get { return Behavior.Registration != null && Behavior.Registration.RestrictAccess; } }

        public void AddBindingParameters(ServiceEndpoint endpoint, System.ServiceModel.Channels.BindingParameterCollection bindingParameters) { }
        public void Validate(ServiceEndpoint endpoint) { }

        object IDispatchMessageInspector.AfterReceiveRequest(ref System.ServiceModel.Channels.Message request, System.ServiceModel.IClientChannel channel, System.ServiceModel.InstanceContext instanceContext)
        {
            if (RestrictAccess)
                Behavior.Registration.Validate(request);

            if (ShouldAudit)
            {                
                return Behavior.Audit.CreateServiceTraceRecord(ref request);
            }

            return null; 
        }

        void IDispatchMessageInspector.BeforeSendReply(ref System.ServiceModel.Channels.Message reply, object correlationState)
        {
            if(ShouldAudit)
            {
                Behavior.Audit.CompleteServiceTraceRecord(ref reply, correlationState);
            }
        }       

        public void ApplyClientBehavior(ServiceEndpoint endpoint, ClientRuntime clientRuntime)
        {

        }

        public void ApplyDispatchBehavior(ServiceEndpoint endpoint, EndpointDispatcher endpointDispatcher)
        {
            endpointDispatcher.DispatchRuntime.MessageInspectors.Add(this);
        }

    }
}
